API Corner - Creating Dialogs by API

Level - Advanced

by Alyce Watson [http://alycesrestaurant.com/]

Home

Container Control

API Dialogs

Place a Dialog

Center a Dialog

LB IDE

Close Multiple Windows

TransparentBlt

Animation Control

Sprite Byte

Qcard DLL

Patterns and Music

Newsletter help

Index


This is an informational article to be used as an adjunct to Brent Thorn's article on Container Controls and Callbacks.

Dialogs in Liberty BASIC

Liberty BASIC uses several standard Windows dialogs, such as the FILEDIALOG, PRINTERDIALOG, COLORDIALOG AND NOTICE. We can also create our own versions of these dialogs with API calls. Windows handles all of the hard stuff for us.

Liberty BASIC also allows us to create dialog-type windows. Windows and dialogs behave differently. Windows can have menus; dialogs cannot. Dialogs trap the press of the ENTER key, while windows do not. Dialogs can be modal, but windows cannot. Modal dialogs must be dismissed before focus can return to another window.

Windows created by API

There are many programs written by LB programmers that create windows and controls with the API CreateWindowExA. Brent has created a dialog by API. This is a bit more complicated than creating a button by API, for instance. It requires a host of API calls, including CALLBACKS. It is definitely a method to be used by experienced programmers. Some languages allow dialog templates to be stored as resources, but Liberty BASIC has no native resource capabilities, so dialogs must be created in memory at runtime.

Why create a dialog by API?

Brent uses this method to create a container control. Issue #108 uses native Liberty BASIC popup windows as container controls. The method works, but Brent's method is better. Here is what Brent has to say about it:

The problem I immediately saw with the popup version is the main window's loss of active status. The container should be completely unrecognizable as such. Most users of Windows don't realize that in all the multipage/tabbed Control Panels not only is the parent window a dialog but so is every page This makes my demo a reflection of a standard Windows idiom albeit Windows itself uses dialog resources, which is easier to use in C/C++ than building a dialog from scratch.

Container Controls

Container controls act as containers for other controls. When the container is moved, shown, or hidden, the controls it contains are also moved. This is very useful along with Tab Controls, as is demonstrated in issue #108.

Dialog Units

Dialogs measure things in Dialog Units rather than in pixels. You obtain the information about dialog units with the GetDialogBaseUnits function. You may wonder why this is necessary. The MSDN tell us:

These measurements are device independent, so an application can use a single template to create the same dialog box for all types of display devices. This ensures that a dialog box will have the same proportions and appearance on all screens despite differing resolutions and aspect ratios between screens.

Template for dialog creation.

The information about the dialog is placed into a STRUCT, or template.

DLGITEMTEMPLATE

The DLGITEMTEMPLATE structure defines the dimensions and style of a control in a dialog box. One or more of these structures are combined with a DLGTEMPLATE structure to form a standard template for a dialog box.

typedef struct {

DWORD style;

DWORD dwExtendedStyle;

short x;

short y;

short cx;

short cy;

WORD id; // Windows 95/98/Me: this is a byte

} DLGITEMTEMPLATE, *PDLGITEMTEMPLATE;

Members

style Specifies the style of the control. This member can be a combination of window style values (such as WS_BORDER) and one or more of the control style values (such as BS_PUSHBUTTON and ES_LEFT).

dwExtendedStyle Specifies extended styles for a window. This member is not used to create controls in dialog boxes, but applications that use dialog box templates can use it to create other types of windows.

x Specifies the x-coordinate, in dialog box units, of the upper-left corner of the control. This coordinate is always relative to the upper-left corner of the dialog box's client area.

y Specifies the y-coordinate, in dialog box units, of the upper-left corner of the control. This coordinate is always relative to the upper-left corner of the dialog box's client area.

cx Specifies the width, in dialog box units, of the control.

cy Specifies the height, in dialog box units, of the control.

id Specifies the control identifier.

Other APIs used.

This method requires memory functions from Kernel32.DLL. It is necessary to set the parent of the created dialog to be the program's window, and it also requires a CALLBACK to handle the processing of messages. It is also necessary to break returned values into their hiword and loword components. Brent demonstrates all of these things in code that is clear, concise and highly readable.

It is beyond the scope of this article to explain all of the functions in detail. Below, find some documentation from the MSDN, the Microsoft Developers Network. You can order your own copy of the MSDN on CDROM. It is a bit pricey. You can, instead, order a CDROM of the Platform SDK for $8.95 US. The MSDN documentation can be read free online here: [MSDN Platform SDK]

When to use a Dialog Box, from MSDN

When to Use a Dialog Box

Most applications use dialog boxes to prompt for additional information for menu items that require user input. Using a dialog box is the only recommended way for an application to retrieve the input. For example, a typical Open menu item requires the name of a file to open, so an application should use a dialog box to prompt the user for the name. In such cases, the application creates the dialog box when the user clicks the menu item and destroys the dialog box immediately after the user supplies the information.

Many applications also use dialog boxes to display information or options while the user works in another window. For example, word processing applications often use a dialog box with a text-search option. While the application searches for the text, the dialog box remains on the screen. The user can then return to the dialog box and search for the same word again; or the user can change the entry in the dialog box and search for a new word. Applications that use dialog boxes in this way typically create one when the user clicks the menu item and continue to display it for as long as the application runs or until the user explicitly closes the dialog box.

To support the different ways applications use dialog boxes, there are two types of dialog box: modal and modeless. A modal dialog box requires the user to supply information or cancel the dialog box before allowing the application to continue. Applications use modal dialog boxes in conjunction with menu items that require additional information before they can proceed. A modeless dialog box allows the user to supply information and return to the previous task without closing the dialog box. Modal dialog boxes are simpler to manage than modeless dialog boxes because they are created, perform their task, and are destroyed by calling a single function.

To create either a modal or modeless dialog box, an application must supply a dialog box template to describe the dialog box style and content; the application must also supply a dialog box procedure to carry out tasks. The dialog box template is a binary description of the dialog box and the controls it contains. The developer can create this template as a resource to be loaded from the application's executable file, or created in memory while the application runs. The dialog box procedure is an application-defined callback function that the system calls when it has input for the dialog box or tasks for the dialog box to carry out. Although a dialog box procedure is similar to a window procedure, it does not have the same responsibilities.

An application typically creates a dialog box by using either the DialogBox or CreateDialog function. DialogBox creates a modal dialog box; CreateDialog creates a modeless dialog box. These two functions load a dialog box template from the application's executable file and create a pop-up window that matches the template's specifications. There are other functions that create a dialog box by using templates in memory; they pass additional information to the dialog box procedure as the dialog box is created.

Dialog boxes usually belong to a predefined, exclusive window class. The system uses this window class and its corresponding window procedure for both modal and modeless dialog boxes. When the function is called, it creates the window for the dialog box, as well as the windows for the controls in the dialog box, then sends selected messages to the dialog box procedure. While the dialog box is visible, the predefined window procedure manages all messages, processing some messages and passing others to the dialog box procedure so that the procedure can carry out tasks. Applications do not have direct access to the predefined window class or window procedure, but they can use the dialog box template and dialog box procedure to modify the style and behavior of a dialog box.

CreateDialogIndirctParamA, from MSDN

CreateDialogIndirectParam

The CreateDialogIndirectParam function creates a modeless dialog box from a dialog box template in memory. Before displaying the dialog box, the function passes an application-defined value to the dialog box procedure as the lParam parameter of the WM_INITDIALOG message. An application can use this value to initialize dialog box controls.

HWND CreateDialogIndirectParam(

HINSTANCE hInstance, // handle to module

LPCDLGTEMPLATE lpTemplate, // dialog box template

HWND hWndParent, // handle to owner window

DLGPROC lpDialogFunc, // dialog box procedure

LPARAM lParamInit // initialization value

);

Parameters

hInstance

[in] Handle to the module that will create the dialog box.

lpTemplate

[in] Pointer to a global memory object that contains the template CreateDialogIndirectParam uses to create the dialog box. A dialog box template consists of a header that describes the dialog box, followed by one or more additional blocks of data that describe each of the controls in the dialog box. The template can use either the standard format or the extended format.

In a standard template, the header is a DLGTEMPLATE structure followed by additional variable-length arrays. The data for each control consists of a DLGITEMTEMPLATE structure followed by additional variable-length arrays.

In an extended dialog box template, the header uses the DLGTEMPLATEEX format and the control definitions use the DLGITEMTEMPLATEEX format.

After CreateDialogIndirectParam returns, you can free the template, which is only used to get the dialog box started.

hWndParent

[in] Handle to the window that owns the dialog box.

lpDialogFunc

[in] Pointer to the dialog box procedure. For more information about the dialog box procedure, see DialogProc.

lParamInit

[in] Specifies the value to pass to the dialog box in the lParam parameter of the WM_INITDIALOG message.

Return Values

If the function succeeds, the return value is the window handle to the dialog box.

If the function fails, the return value is NULL. To get extended error information, call GetLastError.

Remarks

The CreateDialogIndirectParam function uses the CreateWindowEx function to create the dialog box. CreateDialogIndirectParam then sends a WM_INITDIALOG message to the dialog box procedure. If the template specifies the DS_SETFONT or DS_SHELLFONT style, the function also sends a WM_SETFONT message to the dialog box procedure. The function displays the dialog box if the template specifies the WS_VISIBLE style. Finally, CreateDialogIndirectParam returns the window handle to the dialog box.

After CreateDialogIndirectParam returns, you can use the ShowWindow function to display the dialog box (if it is not already visible). To destroy the dialog box, use the DestroyWindow function. To support keyboard navigation and other dialog box functionality, the message loop for the dialog box must call the IsDialogMessage function.

In a standard dialog box template, the DLGTEMPLATE structure and each of the DLGITEMTEMPLATE structures must be aligned on DWORD boundaries. The creation data array that follows a DLGITEMTEMPLATE structure must also be aligned on a DWORD boundary. All of the other variable-length arrays in the template must be aligned on WORD boundaries.

In an extended dialog box template, the DLGTEMPLATEEX header and each of the DLGITEMTEMPLATEEX control definitions must be aligned on DWORD boundaries. The creation data array, if any, that follows a DLGITEMTEMPLATEEX structure must also be aligned on a DWORD boundary. All of the other variable-length arrays in the template must be aligned on WORD boundaries.

All character strings in the dialog box template, such as titles for the dialog box and buttons, must be Unicode strings. To create code that works on both Windows 95/98/Me and Windows NT/2000/XP, use the MultiByteToWideChar function to generate these Unicode strings.

Windows 95/98/Me: The system can support a maximum of 255 controls per dialog box template. To place more than 255 controls in a dialog box, create the controls in the WM_INITDIALOG message handler rather than placing them in the template.

Windows 95/98/Me: CreateDialogIndirectParamW is supported by the Microsoft Layer for Unicode. To use this, you must add certain files to your application, as outlined in Microsoft Layer for Unicode on Windows 95/98/Me Systems.

Requirements

Windows NT/2000/XP: Included in Windows NT 3.1 and later.

Windows 95/98/Me: Included in Windows 95 and later.


Home

Container Control

API Dialogs

Place a Dialog

Center a Dialog

LB IDE

Close Multiple Windows

TransparentBlt

Animation Control

Sprite Byte

Qcard DLL

Patterns and Music

Newsletter help

Index